#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h> // open function
#include <unistd.h> // close function
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>
#include <sys/epoll.h>

const int PORT = 8889;

/*
    listen_loop(): epoll监听套接字，作不同处理
    accept_conn(): 新的客户端连接进来，执行accept，将fd加入epoll set
    recv_message(): recv并且重复输出一份给客户端
 */

void listen_loop(unsigned int sock_fd);
void accept_conn(unsigned int sock_fd, unsigned int epollfd);
void recv_message(unsigned int sock_fd);

int main(void) {
    int sock_fd;
    struct sockaddr_in server_addr;

    //初始化socket
    sock_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (sock_fd < 0) {
        perror("socket:");
        return 0;
    }

    //编辑地址
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;//ipv_4
    server_addr.sin_port = htons(PORT);//监听端口8888
    server_addr.sin_addr.s_addr = INADDR_ANY;//本地的任意地址

    //绑定然后监听
    if (bind(sock_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        perror("bind:");
        return 0;
    }
    if (listen(sock_fd, 10) < 0) {
        perror("listen");
        return 0;
    }

    listen_loop(sock_fd);

    return 0;
}
void accept_conn(unsigned int sock_fd, unsigned int epollfd) {
    struct sockaddr_in clientaddr;
    struct epoll_event event;
    socklen_t len = sizeof(struct sockaddr);
    int accept_fd = 0;

    accept_fd = accept(sock_fd, (struct sockaddr*)&clientaddr, &len);

    if (accept_fd <= 0) {
        perror("accept error");
        return;
    }

    //将新建连接加入epoll set
    event.data.fd = accept_fd;
    event.events = EPOLLIN | EPOLLET | EPOLLRDHUP;
    epoll_ctl(epollfd, EPOLL_CTL_ADD, accept_fd, &event);
    return;
}

void recv_message(unsigned int sock_fd) {
    char recv_buf[1024], send_buf[1024];

    memset(recv_buf, 0, sizeof(recv_buf));
    memset(send_buf, 0, sizeof(send_buf));

    recv(sock_fd, recv_buf, sizeof(recv_buf), 0);
    fputs(recv_buf, stdout);
    strcpy(send_buf, recv_buf);
    send(sock_fd, send_buf, sizeof(send_buf), 0);

    return;
}
void listen_loop(unsigned int sock_fd)
{
    int epollfd, i, ret;
    int timeout = 300;
    struct epoll_event event;
    struct epoll_event eventList[10];

    /*创建epoll监听事件*/
    epollfd = epoll_create(10);
    event.events = EPOLLIN | EPOLLET;
    event.data.fd = sock_fd;

    /*注册epoll监听事件.*/
    if (epoll_ctl(epollfd, EPOLL_CTL_ADD, sock_fd, &event) < 0) {
        printf("register epoll event err !");
        return;
    }

    while (1) {
        ret = epoll_wait(epollfd, eventList, 10, timeout);

        /*epoll事件错误.*/
        if (ret < 0) {
            printf("epoll event err!");
            break;
        }
        /*无事件返回.*/
        else if (ret == 0) {
            continue;
        }

        /*epoll返回事件.*/
        for (i = 0; i < ret; i++) {
            /*epoll 错误*/
            if ((eventList[i].events & EPOLLERR) || (eventList[i].events & EPOLLHUP) || !(eventList[i].events & EPOLLIN)) {
                printf("epoll error\n");
                close(eventList[i].data.fd);
                exit(-1);
            }

            //half connection
            if (eventList[i].events & EPOLLRDHUP) {
                printf("//one client close the conne.//\n");
                close(eventList[i].data.fd);
            }

            /*accept事件*/
            if (eventList[i].data.fd == sock_fd) {
                accept_conn(sock_fd, epollfd);
            }
            /*非sock_fd则为其他事件.*/
            else {
                recv_message(eventList[i].data.fd);
            }
        }
    }
    close(epollfd);
    close(sock_fd);
    return;
}
